// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Pmgjiv

//@version=5
indicator("FluidTrades - SMC", overlay = true, max_labels_count = 500, max_boxes_count = 500, max_lines_count = 500, max_bars_back = 1000)

//
//SETTINGS
//


// On & Off functionality
enableSR = input.bool(false, title = 'Support/Resistance', group = 'On & Off functionality',inline = 'overlayLine1')
enableDS = input.bool(false, title = 'Demand/Supply', group = 'On & Off functionality',inline = 'overlayLine1')

box_ob = input.bool(false, title = 'Toggle Order Block', group = 'On & Off functionality',inline = 'overlayLine2')
box_hide_gray = input.bool(true, title = 'Hide gray boxes', group = 'On & Off functionality',inline = 'overlayLine2')

showIndicator = input.bool(true, title = 'EMA', group = 'On & Off functionality',inline = 'overlayLine3')
showVWAP = input.bool(false, title = 'VWAP', group = 'On & Off functionality',inline = 'overlayLine3')
showORB = input.bool(false, title = 'ORB', group = 'On & Off functionality',inline = 'overlayLine3')
rsicol = input.bool(false, title = 'Show RSI colors?', group = 'On & Off functionality',inline = 'overlayLine3')

volumeProfile = input.bool(false, title = 'Volume Profile', group = 'On & Off functionality',inline = 'overlayLine4')
volumeHistogram = input.bool(false, title = 'Volume Histogram', group = 'On & Off functionality',inline = 'overlayLine4')

trendTable = input.bool(true, title = 'Show Trend Table', group = 'On & Off functionality',inline = 'overlayLine5')
trendCalc       = input.string(defval = "EMA", title = "Trend Mode", options=["Supertrend", "EMA"], group = 'On & Off functionality',inline = 'overlayLine5')
showDXY = input.bool(false, title = 'Show DXY', group = 'On & Off functionality',inline = 'overlayLine5')

show_price_action_labels = input.bool(false, title = 'Show Price Action Labels', group = 'On & Off functionality',inline = 'overlayLine6')
show_zigzag = input.bool(false, title = 'Show Zig Zag', group = 'On & Off functionality', inline = 'overlayLine6')

showTL = input.bool(false, title = 'TrendLine', group = 'On & Off functionality', inline = 'overlayLine7')
periodlen   = input.string('Adaptive', 'Trendline Term', ['Long Term', 'Short Term','Adaptive'], group = 'On & Off functionality', inline = 'overlayLine7')
showSR = input.bool(false, title = 'S&R', group = 'On & Off functionality', inline = 'overlayLine7')
timef  = input.timeframe("", "", group = 'On & Off functionality', inline = 'overlayLine7')


//      INDICATOR SETTINGS
swing_length = input.int(10, title = 'Swing High/Low Length', group = 'Settings', minval = 1, maxval = 50)
history_of_demand_to_keep = input.int(20, title = 'History To Keep', minval = 5, maxval = 50)
box_width = input.float(10, title = 'Supply/Demand Box Width', group = 'Settings', minval = 1, maxval = 10, step = 0.5)

//      INDICATOR VISUAL SETTINGS
// show_zigzag = input.bool(false, title = 'Show Zig Zag', group = 'Visual Settings', inline = '1')
// show_price_action_labels = input.bool(false, title = 'Show Price Action Labels', group = 'Visual Settings', inline = '2')

supply_color = input.color(color.new(#EDEDED,70), title = 'Supply', group = 'Visual Settings', inline = '3')
supply_outline_color = input.color(color.new(color.white,75), title = 'Outline', group = 'Visual Settings', inline = '3')

demand_color = input.color(color.new(#00FFFF,70), title = 'Demand', group = 'Visual Settings', inline = '4')
demand_outline_color = input.color(color.new(color.white,75), title = 'Outline', group = 'Visual Settings', inline = '4')

bos_label_color = input.color(color.white, title = 'BOS Label', group = 'Visual Settings', inline = '5')
poi_label_color = input.color(color.white, title = 'POI Label', group = 'Visual Settings', inline = '7')

swing_type_color = input.color(color.lime, title = 'Price Action Label', group = 'Visual Settings', inline = '8')
zigzag_color = input.color(color.new(#000000,0), title = 'Zig Zag', group = 'Visual Settings', inline = '9')

//
//END SETTINGS
//


//
//FUNCTIONS
//

//      FUNCTION TO ADD NEW AND REMOVE LAST IN ARRAY
f_array_add_pop(array, new_value_to_add) =>
    array.unshift(array, new_value_to_add)
    array.pop(array)

//      FUNCTION SWING H & L LABELS
f_sh_sl_labels(array, swing_type) =>

    var string label_text = na
    if swing_type == 1
        if array.get(array, 0) >= array.get(array, 1)
            label_text := 'HH'
        else
            label_text := 'LH'
        label.new(bar_index - swing_length, array.get(array,0), text = label_text, style=label.style_label_down, textcolor = swing_type_color, color = color.new(swing_type_color, 100), size = size.tiny)
    
    else if swing_type == -1
        if array.get(array, 0) >= array.get(array, 1)
            label_text := 'HL'
        else
            label_text := 'LL'
        label.new(bar_index - swing_length, array.get(array,0), text = label_text, style=label.style_label_up, textcolor = swing_type_color, color = color.new(swing_type_color, 100), size = size.tiny)

//      FUNCTION MAKE SURE SUPPLY ISNT OVERLAPPING
f_check_overlapping(new_poi, box_array, atr) =>

    atr_threshold = atr * 2
    okay_to_draw = true

    for i = 0 to array.size(box_array) - 1
        top = box.get_top(array.get(box_array, i))
        bottom = box.get_bottom(array.get(box_array, i))
        poi = (top + bottom) / 2

        upper_boundary = poi + atr_threshold
        lower_boundary = poi - atr_threshold

        if new_poi >= lower_boundary and new_poi <= upper_boundary
            okay_to_draw := false
            break
        else 
            okay_to_draw := true
    okay_to_draw


//      FUNCTION TO DRAW SUPPLY OR DEMAND ZONE
f_supply_demand(value_array, bn_array, box_array, label_array, box_type, atr) =>

    atr_buffer = atr * (box_width / 10)
    box_left = array.get(bn_array, 0)
    box_right = bar_index

    var float box_top = 0.00
    var float box_bottom = 0.00
    var float poi = 0.00


    if box_type == 1
        box_top := array.get(value_array, 0)
        box_bottom := box_top - atr_buffer
        poi := (box_top + box_bottom) / 2
    else if box_type == -1
        box_bottom := array.get(value_array, 0)
        box_top := box_bottom + atr_buffer
        poi := (box_top + box_bottom) / 2

    okay_to_draw = f_check_overlapping(poi, box_array, atr)
    // okay_to_draw = true

    //delete oldest box, and then create a new box and add it to the array
    if box_type == 1 and okay_to_draw and enableDS
        box.delete( array.get(box_array, array.size(box_array) - 1) )
        f_array_add_pop(box_array, box.new( left = box_left, top = box_top, right = box_right, bottom = box_bottom, border_color = supply_outline_color,
             bgcolor = supply_color, extend = extend.right, text = 'SUPPLY', text_halign = text.align_center, text_valign = text.align_center, text_color = poi_label_color, text_size = size.small, xloc = xloc.bar_index))
        
        box.delete( array.get(label_array, array.size(label_array) - 1) )
        f_array_add_pop(label_array, box.new( left = box_left, top = poi, right = box_right, bottom = poi, border_color = color.new(poi_label_color,90),
             bgcolor = color.new(poi_label_color,90), extend = extend.right, text = 'POI', text_halign = text.align_left, text_valign = text.align_center, text_color = poi_label_color, text_size = size.small, xloc = xloc.bar_index))

    else if box_type == -1 and okay_to_draw and enableDS
        box.delete( array.get(box_array, array.size(box_array) - 1) )
        f_array_add_pop(box_array, box.new( left = box_left, top = box_top, right = box_right, bottom = box_bottom, border_color = demand_outline_color,
             bgcolor = demand_color, extend = extend.right,  text = 'DEMAND', text_halign = text.align_center, text_valign = text.align_center, text_color = poi_label_color, text_size = size.small, xloc = xloc.bar_index))
        
        box.delete( array.get(label_array, array.size(label_array) - 1) )
        f_array_add_pop(label_array, box.new( left = box_left, top = poi, right = box_right, bottom = poi, border_color = color.new(poi_label_color,90),
             bgcolor = color.new(poi_label_color,90), extend = extend.right,  text = 'POI', text_halign = text.align_left, text_valign = text.align_center, text_color = poi_label_color, text_size = size.small, xloc = xloc.bar_index))


//      FUNCTION TO CHANGE SUPPLY/DEMAND TO A BOS IF BROKEN
f_sd_to_bos(box_array, bos_array, label_array, zone_type) =>

    if zone_type == 1
        for i = 0 to array.size(box_array) - 1
            level_to_break = box.get_top(array.get(box_array,i))
            // if ta.crossover(close, level_to_break)
            if close >= level_to_break
                copied_box = box.copy(array.get(box_array,i))
                f_array_add_pop(bos_array, copied_box)
                mid = (box.get_top(array.get(box_array,i)) + box.get_bottom(array.get(box_array,i))) / 2
                box.set_top(array.get(bos_array,0), mid)
                box.set_bottom(array.get(bos_array,0), mid)
                box.set_extend( array.get(bos_array,0), extend.none)
                box.set_right( array.get(bos_array,0), bar_index)
                box.set_text( array.get(bos_array,0), 'BOS' )
                box.set_text_color( array.get(bos_array,0), bos_label_color)
                box.set_text_size( array.get(bos_array,0), size.small)
                box.set_text_halign( array.get(bos_array,0), text.align_center)
                box.set_text_valign( array.get(bos_array,0), text.align_center)
                box.delete(array.get(box_array, i))
                box.delete(array.get(label_array, i))


    if zone_type == -1
        for i = 0 to array.size(box_array) - 1
            level_to_break = box.get_bottom(array.get(box_array,i))
            // if ta.crossunder(close, level_to_break)
            if close <= level_to_break
                copied_box = box.copy(array.get(box_array,i))
                f_array_add_pop(bos_array, copied_box)
                mid = (box.get_top(array.get(box_array,i)) + box.get_bottom(array.get(box_array,i))) / 2
                box.set_top(array.get(bos_array,0), mid)
                box.set_bottom(array.get(bos_array,0), mid)
                box.set_extend( array.get(bos_array,0), extend.none)
                box.set_right( array.get(bos_array,0), bar_index)
                box.set_text( array.get(bos_array,0), 'BOS' )
                box.set_text_color( array.get(bos_array,0), bos_label_color)
                box.set_text_size( array.get(bos_array,0), size.small)
                box.set_text_halign( array.get(bos_array,0), text.align_center)
                box.set_text_valign( array.get(bos_array,0), text.align_center)
                box.delete(array.get(box_array, i))
                box.delete(array.get(label_array, i))



//      FUNCTION MANAGE CURRENT BOXES BY CHANGING ENDPOINT
f_extend_box_endpoint(box_array) =>

    for i = 0 to array.size(box_array) - 1
        box.set_right(array.get(box_array, i), bar_index + 100)


//
//END FUNCTIONS
//  


//
//CALCULATIONS
//

//      CALCULATE ATR 
atr = ta.atr(50)

//      CALCULATE SWING HIGHS & SWING LOWS
swing_high = ta.pivothigh(high, swing_length, swing_length)
swing_low = ta.pivotlow(low, swing_length, swing_length)

//      ARRAYS FOR SWING H/L & BN 
var swing_high_values = array.new_float(5,0.00)
var swing_low_values = array.new_float(5,0.00)

var swing_high_bns = array.new_int(5,0)
var swing_low_bns = array.new_int(5,0)

//      ARRAYS FOR SUPPLY / DEMAND
var current_supply_box = array.new_box(history_of_demand_to_keep, na)
var current_demand_box = array.new_box(history_of_demand_to_keep, na)

//      ARRAYS FOR SUPPLY / DEMAND POI LABELS
var current_supply_poi = array.new_box(history_of_demand_to_keep, na)
var current_demand_poi = array.new_box(history_of_demand_to_keep, na)

//      ARRAYS FOR BOS
var supply_bos = array.new_box(5, na)
var demand_bos = array.new_box(5, na)
//
//END CALCULATIONS
//

//      NEW SWING HIGH
if not na(swing_high)

    //MANAGE SWING HIGH VALUES
    f_array_add_pop(swing_high_values, swing_high)
    f_array_add_pop(swing_high_bns, bar_index[swing_length])
    if show_price_action_labels
        f_sh_sl_labels(swing_high_values, 1)

    f_supply_demand(swing_high_values, swing_high_bns, current_supply_box, current_supply_poi, 1, atr)

//      NEW SWING LOW
else if not na(swing_low)

    //MANAGE SWING LOW VALUES
    f_array_add_pop(swing_low_values, swing_low)
    f_array_add_pop(swing_low_bns, bar_index[swing_length])
    if show_price_action_labels
        f_sh_sl_labels(swing_low_values, -1)
    
    f_supply_demand(swing_low_values, swing_low_bns, current_demand_box, current_demand_poi, -1, atr)


f_sd_to_bos(current_supply_box, supply_bos, current_supply_poi, 1)
f_sd_to_bos(current_demand_box, demand_bos, current_demand_poi, -1)

f_extend_box_endpoint(current_supply_box)
f_extend_box_endpoint(current_demand_box)

//ZIG ZAG
h = ta.highest(high, swing_length * 2 + 1)
l = ta.lowest(low, swing_length * 2 + 1)
f_isMin(len) =>
    l == low[len]
f_isMax(len) =>
    h == high[len]

var dirUp = false
var lastLow = high * 100
var lastHigh = 0.0
var timeLow = bar_index
var timeHigh = bar_index
var line li = na

f_drawLine() =>
    _li_color = show_zigzag ? zigzag_color : color.new(#ffffff,100)
    line.new(timeHigh - swing_length, lastHigh, timeLow - swing_length, lastLow, xloc.bar_index, color=_li_color, width=2)

if dirUp
    if f_isMin(swing_length) and low[swing_length] < lastLow
        lastLow := low[swing_length]
        timeLow := bar_index
        line.delete(li)
        li := f_drawLine()
        li

    if f_isMax(swing_length) and high[swing_length] > lastLow
        lastHigh := high[swing_length]
        timeHigh := bar_index
        dirUp := false
        li := f_drawLine()
        li

if not dirUp
    if f_isMax(swing_length) and high[swing_length] > lastHigh
        lastHigh := high[swing_length]
        timeHigh := bar_index
        line.delete(li)
        li := f_drawLine()
        li
    if f_isMin(swing_length) and low[swing_length] < lastHigh
        lastLow := low[swing_length]
        timeLow := bar_index
        dirUp := true
        li := f_drawLine()
        if f_isMax(swing_length) and high[swing_length] > lastLow
            lastHigh := high[swing_length]
            timeHigh := bar_index
            dirUp := false
            li := f_drawLine()
            li
// if barstate.islast
    // label.new(x = bar_index + 10, y = close[1], text = str.tostring( array.size(current_supply_poi) ))
//     label.new(x = bar_index + 20, y = close[1], text = str.tostring( box.get_bottom( array.get(current_supply_box, 0))))
//     label.new(x = bar_index + 30, y = close[1], text = str.tostring( box.get_bottom( array.get(current_supply_box, 1))))
//     label.new(x = bar_index + 40, y = close[1], text = str.tostring( box.get_bottom( array.get(current_supply_box, 2))))
//     label.new(x = bar_index + 50, y = close[1], text = str.tostring( box.get_bottom( array.get(current_supply_box, 3))))
//     label.new(x = bar_index + 60, y = close[1], text = str.tostring( box.get_bottom( array.get(current_supply_box, 4))))






// VWAP
// showVWAP = input(true, "on/off VWAP")
// Input options
averageData = input.source(close, title="Average Data Source")
// Calculate the volume-weighted average price and its 'noise' bands
vwapData  = ta.vwap(averageData)
// Plot the average and its band
plot(showVWAP ? vwapData : na, color=color.red, title="VWAP",style = plot.style_circles)


// EMA
// showIndicator = input(true, "on/off EMA")

length1 = input(9, "EMA Length 1")
length2 = input(21, "EMA Length 2")
length3 = input(50, "EMA Length 3")
length4 = input(100, "EMA Length 4")
length5 = input(200, "EMA Length 5")

src = input(close, "Source")

ema1 = ta.ema(src, length1)
ema2 = ta.ema(src, length2)
ema3 = ta.ema(src, length3)
ema4 = ta.ema(src, length4)
ema5 = ta.ema(src, length5)

plot(showIndicator ? ema1 : na, color=color.orange, title="EMA 1")
plot(showIndicator ? ema2 : na, color=color.green, title="EMA 2")
plot(showIndicator ? ema3 : na, color=color.yellow, title="EMA 3")
plot(showIndicator ? ema4 : na, color=color.blue, title="EMA 4")
plot(showIndicator ? ema5 : na, color=color.red, title="EMA 5")




//Open Range Breakout
// showORB = input(true, "on/off Open Range Breakout")
inputMax = input(15, title='ORB total time (minutes)')
sess = input.session('0915-0930', title='Session Time')
t = time(timeframe.period, sess + ':1234567')
hide = timeframe.isintraday and timeframe.multiplier <= inputMax

is_newbar_(res) =>
    ta.change(time(res)) != 0
in_session = not na(t)
is_first = in_session and not in_session[1]

orb_high = float(na)
orb_low = float(na)

if is_first
    orb_high := high
    orb_low := low
    orb_low
else
    orb_high := orb_high[1]
    orb_low := orb_low[1]
    orb_low
if high > orb_high and in_session
    orb_high := high
    orb_high
if low < orb_low and in_session
    orb_low := low
    orb_low

plot(showORB ? orb_high : na, style=plot.style_line, color=orb_high[1] != orb_high ? na : color.green, title='ORB High', linewidth=2)
plot(showORB ? orb_low : na, style=plot.style_line, color=orb_low[1] != orb_low ? na : color.red, title='ORB Low', linewidth=2)



//Volume Profile

//.....................................................//

f_drawLabelX(_x, _y, _text, _xloc, _yloc, _color, _style, _textcolor, _size, _textalign, _tooltip) =>
    var id = label.new(_x, _y, _text, _xloc, _yloc, _color, _style, _textcolor, _size, _textalign, _tooltip)
    label.set_xy(id, _x, _y)
    label.set_text(id, _text)
    label.set_tooltip(id, _tooltip)
    label.set_textcolor(id, _textcolor)

// Functions  ----------------------------------------------------------------------------------- //
// ---------------------------------------------------------------------------------------------- //

// ---------------------------------------------------------------------------------------------- //
// Volume Profile (Price by Volume) / Volume Histogram ------------------------------------------ //

group_volume_profile    = 'Volume Profile / Price by Volume'
tooltip_volume_profile  = 'Volume Profile (also known as Price by Volume) is an charting study that displays trading activity over a specified time period at specific price levels'

// volumeProfile     = input.bool(true, 'Volume Profile', group = group_volume_profile, tooltip = tooltip_volume_profile)
lookbackLength    = input.int(150, 'Lookback Length', minval = 10, maxval = 5000, step = 10 , group = group_volume_profile)
profileLevels     = input.int(100, 'Number of Rows' , minval = 10, maxval = 150 , step = 1  , group = group_volume_profile)
profileDisplay    = input.string('Up/Down', 'Volume', options = ['Up/Down', 'Total'], group = group_volume_profile)
upVolumeColor     = color.new(#1592e6, 30)
downVolumeColor   = color.new(#fbc123, 30)
totalVolumeColor  = color.new(#801922, 30)
backgroundColor   = color.new(#2962ff, 95)
pointOfControl    = input.bool(true, 'Show Point of Control', inline='PoC', group = group_volume_profile)
pocColor          = color.new(#ff0000, 0)
bullBearStr       = input.bool(true, 'Show Bull/Bear Volume Strength', inline='BB' , group = group_volume_profile)
bbStrUpColor      = color.new(#26a69a, 30)
bbStrDownColor    = color.new(#ef5350, 30)
priceLevels       = input.bool(false, 'Show Price Levels'                                    , group = group_volume_profile)
profilePlacement  = input.string('Right', 'Placment', options = ['Right', 'Left']           , group = group_volume_profile)
profileWidth      = input.int(30, 'Profile Width', minval = 21, maxval = 150                , group = group_volume_profile)
horizontalOffset  = input.int(10, 'Horizontal Offset', minval = 0 , maxval = 50             , group = group_volume_profile)

group_volume      = 'Volume Histogram'
tooltip_volume    = 'The Volume indicator is used to measure how much of a given financial asset has traded in a specific period of time'
// volumeHistogram   = input.bool(true, 'Volume Histogram'                                       , group = group_volume, tooltip = tooltip_volume)
volumePlacement   = input.string('Top', 'Placment', options = ['Top', 'Bottom'], inline='VOL' , group = group_volume)
volumeHistHight   = 11 - input.int(8, 'Hight' , minval = 1, maxval = 10        , inline='VOL' , group = group_volume)
volumeMA          = input.bool(true, 'Volume MA, Length'                       , inline='vol2', group = group_volume)
volumeMALength    = input.int(21, '', minval = 1                               , inline='vol2', group = group_volume)
volumeUpColor     = color.new(#26a69a, 30)
volumeDownColor   = color.new(#ef5350, 30)
volumeMAColor     = color.new(#2962ff, 0)
volumeStorageT    = array.new_float(profileLevels + 1, 0.)
volumeStorageB    = array.new_float(profileLevels + 1, 0.)
var a_profile     = array.new_box()
var a_histogram   = array.new_line()
priceHighest      = ta.highest(high, lookbackLength)
priceLowest       = ta.lowest (low , lookbackLength)
priceStep         = (priceHighest - priceLowest) / profileLevels
priceChangeRate   = (priceHighest - priceLowest) / priceHighest 
barPriceLow       = low
barPriceHigh      = high
bullCandle        = close > open
nzVolume          = nz(volume)
volumeHighest     = ta.highest(nzVolume, lookbackLength)
volumeMARate      = nzVolume/ta.sma(nzVolume, volumeMALength)

if barstate.islast and nzVolume and volumeProfile
    if array.size(a_profile) > 0
        for i = 1 to array.size(a_profile)
            box.delete(array.shift(a_profile))
 
    if array.size(a_histogram) > 0
        for i = 1 to array.size(a_histogram)
            line.delete(array.shift(a_histogram))
            
    if priceLevels
        f_drawLabelX(bar_index + (profilePlacement == 'Right' ? profileWidth + horizontalOffset : 0), priceHighest, str.tostring(priceHighest, format.mintick), xloc.bar_index, yloc.price, color.new(upVolumeColor  , 89), profilePlacement == 'Left' and volumePlacement == 'Top'    ? label.style_label_left : label.style_label_down, upVolumeColor  , size.normal, text.align_left, 'Profile High - during last ' + str.tostring(lookbackLength) + ' bars\n %' + str.tostring((priceHighest - priceLowest) / priceLowest  * 100, '#.##') + ' higher than the Profile Low')
        f_drawLabelX(bar_index + (profilePlacement == 'Right' ? profileWidth + horizontalOffset : 0), priceLowest , str.tostring(priceLowest , format.mintick), xloc.bar_index, yloc.price, color.new(downVolumeColor, 89), profilePlacement == 'Left' and volumePlacement == 'Bottom' ? label.style_label_left : label.style_label_up  , downVolumeColor, size.normal, text.align_left, 'Profile Low - during last ' + str.tostring(lookbackLength) + ' bars\n %'  + str.tostring((priceHighest - priceLowest) / priceHighest * 100, '#.##') + ' lower than the Profile High')

    for barIndex = 0 to lookbackLength - 1
        level = 0
        for priceLevel = priceLowest to priceHighest by priceStep
            if barPriceHigh[barIndex] >= priceLevel and barPriceLow[barIndex] < priceLevel + priceStep
                array.set(volumeStorageT, level, array.get(volumeStorageT, level) + nzVolume[barIndex] * ((barPriceHigh[barIndex] - barPriceLow[barIndex]) == 0 ? 1 : priceStep / (barPriceHigh[barIndex] - barPriceLow[barIndex])) )
                
                if bullCandle[barIndex] and (profileDisplay == 'Up/Down' or bullBearStr)
                    array.set(volumeStorageB, level, array.get(volumeStorageB, level) + nzVolume[barIndex] * ((barPriceHigh[barIndex] - barPriceLow[barIndex]) == 0 ? 1 : priceStep / (barPriceHigh[barIndex] - barPriceLow[barIndex])) )
            level += 1
        
        if volumeHistogram and array.size(a_histogram) < 500
            array.push(a_histogram, line.new(bar_index[barIndex], volumePlacement == 'Top' ? priceHighest * (1 + priceChangeRate * .05) : priceLowest  * (1 - priceChangeRate * .05) , bar_index[barIndex], (volumePlacement == 'Top' ? priceHighest * (1 + priceChangeRate * .05) : priceLowest  * (1 - priceChangeRate * .05)) * (1 + ( volumePlacement == 'Top' ? 1 : -1) * nzVolume[barIndex] / volumeHighest * priceChangeRate / volumeHistHight), xloc.bar_index, extend.none, bullCandle[barIndex] ? volumeUpColor : volumeDownColor, line.style_solid, 2))
            
            if volumeMA
                array.push(a_histogram, line.new(bar_index[barIndex], (volumePlacement == 'Top' ? priceHighest * (1 + priceChangeRate * .05) : priceLowest  * (1 - priceChangeRate * .05)) * (1 + (volumePlacement == 'Top' ? 1 : -1) * nzVolume[barIndex] / volumeHighest * priceChangeRate / volumeHistHight / volumeMARate[barIndex]), bar_index[barIndex + 1], (volumePlacement == 'Top' ? priceHighest * (1 + priceChangeRate * .05) : priceLowest  * (1 - priceChangeRate * .05)) * (1 + (volumePlacement == 'Top' ? 1 : -1) * nzVolume[barIndex + 1] / volumeHighest * priceChangeRate / volumeHistHight / volumeMARate[barIndex + 1]), xloc.bar_index, extend.none, volumeMAColor, line.style_solid, 2))

    array.push(a_profile, box.new(bar_index - lookbackLength + 1, priceLowest, bar_index + (profilePlacement == 'Right' ? profileWidth + horizontalOffset : 0), priceHighest, backgroundColor, 1, line.style_dotted, bgcolor = backgroundColor ))
    
    if pointOfControl
        array.push(a_profile, box.new(bar_index - lookbackLength + 1, priceLowest + (array.indexof(volumeStorageT, array.max(volumeStorageT)) + .40) * priceStep, bar_index + (profilePlacement == 'Right' ? profileWidth : 0), priceLowest + (array.indexof(volumeStorageT, array.max(volumeStorageT)) + .60) * priceStep, pocColor, bgcolor = pocColor ))
        
        if priceLevels
            f_drawLabelX(bar_index + (profilePlacement == 'Right' ? horizontalOffset + 5 : 7), priceLowest + (array.indexof(volumeStorageT, array.max(volumeStorageT)) + .5) * priceStep, str.tostring(priceLowest + (array.indexof(volumeStorageT, array.max(volumeStorageT)) + .5) * priceStep, format.mintick), xloc.bar_index, yloc.price, color.new(pocColor, 89), (profilePlacement == 'Right' ? label.style_label_up : label.style_label_left), color.new(pocColor, 0), size.normal, text.align_left, 'Point Of Control Price')

    for level = 0 to profileLevels - 1
        levelColor = profileDisplay == 'Up/Down' ? downVolumeColor : totalVolumeColor
        startBoxIndex = profilePlacement == 'Right' ? bar_index + profileWidth + horizontalOffset - int(array.get(volumeStorageT, level) / array.max(volumeStorageT) * (profileWidth - 9)) : bar_index - lookbackLength + 1
        endBoxIndex   = profilePlacement == 'Right' ? bar_index + profileWidth + horizontalOffset:  startBoxIndex + int( array.get(volumeStorageT, level) / array.max(volumeStorageT) * (profileWidth - 9))
        array.push(a_profile, box.new(startBoxIndex, priceLowest + (level + 0.1) * priceStep, endBoxIndex, priceLowest + (level + 0.9) * priceStep, levelColor, bgcolor = levelColor ))

        if profileDisplay == 'Up/Down'
            startBoxIndex := profilePlacement == 'Right' ? bar_index + profileWidth + horizontalOffset - int(array.get(volumeStorageB, level) / array.max(volumeStorageB) * (profileWidth - 9) / 2) : bar_index - lookbackLength + 1
            endBoxIndex   := profilePlacement == 'Right' ? bar_index + profileWidth + horizontalOffset:  startBoxIndex + int( array.get(volumeStorageB, level) / array.max(volumeStorageB) * (profileWidth - 9) / 2)
            array.push(a_profile, box.new(startBoxIndex, priceLowest + (level + 0.1) * priceStep, endBoxIndex, priceLowest + (level + 0.9) * priceStep, upVolumeColor, bgcolor = upVolumeColor ))
        
        if bullBearStr
            bullBearPower  = 2 * array.get(volumeStorageB, level) - array.get(volumeStorageT, level)
            startBoxIndex := profilePlacement == 'Right' ? bar_index + profileWidth + 1 + horizontalOffset + (bullBearPower > 0 ? 1 : -1) * int(bullBearPower / array.max(volumeStorageT) * (profileWidth - 9) * 1.75) : bar_index - lookbackLength
            endBoxIndex   := profilePlacement == 'Right' ? bar_index + profileWidth + 1 + horizontalOffset:  startBoxIndex + (bullBearPower > 0 ? -1 : 1) * int(bullBearPower / array.max(volumeStorageT) * (profileWidth - 9) * 1.75 )
            array.push(a_profile, box.new(startBoxIndex, priceLowest + (level + 0.1) * priceStep, endBoxIndex, priceLowest + (level + 0.9) * priceStep, bullBearPower > 0 ? bbStrUpColor : bbStrDownColor, bgcolor = bullBearPower > 0 ? bbStrUpColor : bbStrDownColor ))




// 8888888888 8888888b.  8888888888 8888888888             d8888 888      .d8888b.   .d88888b.              As you
// 888        888   Y88b 888        888                   d88888 888     d88P  Y88b d88P" "Y88b             Can see
// 888        888    888 888        888                  d88P888 888     888    888 888     888             Are all
// 8888888    888   d88P 8888888    8888888             d88P 888 888     888        888     888 .d8888b     Basic free
// 888        8888888P"  888        888                d88P  888 888     888  88888 888     888 88K         tradingview
// 888        888 T88b   888        888               d88P   888 888     888    888 888     888 "Y8888b.    indicators
// 888        888  T88b  888        888              d8888888888 888     Y88b  d88P Y88b. .d88P      X88    repackaged
// 888        888   T88b 8888888888 8888888888      d88P     888 88888888 "Y8888P88  "Y88888P"   88888P'    into one
//
// FAQ
//
// Why?
// I want you to see what you are willing to pay hundereds of dollars a month

// Has the code been leaked/hacked?
// No, this code has been created only using common sense and public information from the internet

// What's the accuracy I can expect from this version of the indicator?
// I'd say it's about 95% the same as the one you would pay

// The indicator needs to be updated?
// Write me a private message on TradingView (Nick42_for_win)

// Can I suggest an indicator to get a FREE ALGOs version?
// Write me a private message on TradingView (Nick42_for_win)

// Do you get any monetary return from this project?
// Nope, 0$

// Enjoy ;)

//------------------- EzAlgo SR | https://www.ezalgo.co ----------------------//
// Get user input
// enableSR   = input(true, "SR On/Off", group="SR")
colorSup   = input(#00DBFF, "Support Color", group="SR")
colorRes   = input(#E91E63, "Resistance Color", group="SR")
strengthSR = input.int(2, "S/R Strength", 1, group="SR")
lineStyle  = input.string("Dotted", "Line Style", ["Solid", "Dotted", "Dashed"], group="SR")
lineWidth  = input.int(2, "S/R Line Width", 1, group="SR")
useZones   = input(true, "Zones On/Off", group="SR")
useHLZones = input(true, "High Low Zones On/Off", group="SR")
zoneWidth  = input.int(2, "Zone Width %", 0, tooltip="it's calculated using % of the distance between highest/lowest in last 300 bars", group="SR")
expandSR   = input(true, "Expand SR")
// Functions
percWidth(len, perc) => (ta.highest(len) - ta.lowest(len)) * perc / 100
// Get components
rb            = 10
prd           = 284
ChannelW      = 10
label_loc     = 55
style_         = lineStyle == "Solid" ? line.style_solid : lineStyle == "Dotted" ? line.style_dotted : line.style_dashed
ph            = ta.pivothigh(rb, rb)
pl            = ta.pivotlow (rb, rb)
sr_levels     = array.new_float(21, na)
prdhighest    = ta.highest(prd)
prdlowest     = ta.lowest(prd)
cwidth        = percWidth(prd, ChannelW)
zonePerc      = percWidth(300, zoneWidth)
aas           = array.new_bool(41, true)
u1            = 0.0, u1 := nz(u1[1])
d1            = 0.0, d1 := nz(d1[1])
highestph     = 0.0, highestph := highestph[1]
lowestpl      = 0.0, lowestpl := lowestpl[1]
var sr_levs   = array.new_float(21, na)
label hlabel  = na, label.delete(hlabel[1])
label llabel  = na, label.delete(llabel[1])
var sr_lines  = array.new_line(21, na)
var sr_linesH = array.new_line(21, na)
var sr_linesL = array.new_line(21, na)
var sr_linesF = array.new_linefill(21, na)
var sr_labels = array.new_label(21, na)
if ph or pl
    for x = 0 to array.size(sr_levels) - 1
        array.set(sr_levels, x, na)
    highestph := prdlowest
    lowestpl := prdhighest
    countpp = 0
    for x = 0 to prd
        if na(close[x])
            break
        if not na(ph[x]) or not na(pl[x])
            highestph := math.max(highestph, nz(ph[x], prdlowest), nz(pl[x], prdlowest))
            lowestpl := math.min(lowestpl, nz(ph[x], prdhighest), nz(pl[x], prdhighest))
            countpp += 1
            if countpp > 40
                break
            if array.get(aas, countpp)
                upl = (ph[x] ? high[x + rb] : low[x + rb]) + cwidth
                dnl = (ph[x] ? high[x + rb] : low[x + rb]) - cwidth
                u1 := countpp == 1 ? upl : u1
                d1 := countpp == 1 ? dnl : d1
                tmp = array.new_bool(41, true)
                cnt = 0
                tpoint = 0
                for xx = 0 to prd
                    if na(close[xx])
                        break
                    if not na(ph[xx]) or not na(pl[xx])
                        chg = false
                        cnt += 1
                        if cnt > 40
                            break
                        if array.get(aas, cnt)
                            if not na(ph[xx])
                                if high[xx + rb] <= upl and high[xx + rb] >= dnl
                                    tpoint += 1
                                    chg := true
                            if not na(pl[xx])
                                if low[xx + rb] <= upl and low[xx + rb] >= dnl
                                    tpoint += 1
                                    chg := true
                        if chg and cnt < 41
                            array.set(tmp, cnt, false)
                if tpoint >= strengthSR
                    for g = 0 to 40 by 1
                        if not array.get(tmp, g)
                            array.set(aas, g, false)
                    if ph[x] and countpp < 21
                        array.set(sr_levels, countpp, high[x + rb])
                    if pl[x] and countpp < 21
                        array.set(sr_levels, countpp, low[x + rb])
// Plot
var line highest_ = na, line.delete(highest_)
var line lowest_  = na, line.delete(lowest_)
var line highest_fill1 = na, line.delete(highest_fill1)
var line highest_fill2 = na, line.delete(highest_fill2)
var line lowest_fill1  = na, line.delete(lowest_fill1)
var line lowest_fill2  = na, line.delete(lowest_fill2)
hi_col = close >= highestph ? colorSup : colorRes
lo_col = close >= lowestpl  ? colorSup : colorRes
if enableSR
    highest_ := line.new(bar_index - 311, highestph, bar_index, highestph, xloc.bar_index, expandSR ? extend.both : extend.right, hi_col, style_, lineWidth)
    lowest_  := line.new(bar_index - 311, lowestpl , bar_index, lowestpl , xloc.bar_index, expandSR ? extend.both : extend.right, lo_col, style_, lineWidth)
    if useHLZones
        highest_fill1 := line.new(bar_index - 311, highestph + zonePerc, bar_index, highestph + zonePerc, xloc.bar_index, expandSR ? extend.both : extend.right, na)
        highest_fill2 := line.new(bar_index - 311, highestph - zonePerc, bar_index, highestph - zonePerc, xloc.bar_index, expandSR ? extend.both : extend.right, na)
        lowest_fill1  := line.new(bar_index - 311, lowestpl + zonePerc , bar_index, lowestpl + zonePerc , xloc.bar_index, expandSR ? extend.both : extend.right, na)
        lowest_fill2  := line.new(bar_index - 311, lowestpl - zonePerc , bar_index, lowestpl - zonePerc , xloc.bar_index, expandSR ? extend.both : extend.right, na)
        linefill.new(highest_fill1, highest_fill2, color.new(hi_col, 80))
        linefill.new(lowest_fill1 , lowest_fill2 , color.new(lo_col, 80))
if ph or pl
    for x = 0 to array.size(sr_lines) - 1
        array.set(sr_levs, x, array.get(sr_levels, x))
for x = 0 to array.size(sr_lines) - 1
    line.delete(array.get(sr_lines, x))
    line.delete(array.get(sr_linesH, x))
    line.delete(array.get(sr_linesL, x))
    linefill.delete(array.get(sr_linesF, x))
    if array.get(sr_levs, x) and enableSR
        line_col = close >= array.get(sr_levs, x) ? colorSup : colorRes
        array.set(sr_lines, x, line.new(bar_index - 355, array.get(sr_levs, x), bar_index, array.get(sr_levs, x), xloc.bar_index, expandSR ? extend.both : extend.right, line_col, style_, lineWidth))
        if useZones
            array.set(sr_linesH, x, line.new(bar_index - 355, array.get(sr_levs, x) + zonePerc, bar_index, array.get(sr_levs, x) + zonePerc, xloc.bar_index, expandSR ? extend.both : extend.right, na))
            array.set(sr_linesL, x, line.new(bar_index - 355, array.get(sr_levs, x) - zonePerc, bar_index, array.get(sr_levs, x) - zonePerc, xloc.bar_index, expandSR ? extend.both : extend.right, na))
            array.set(sr_linesF, x, linefill.new(array.get(sr_linesH, x), array.get(sr_linesL, x), color.new(line_col, 80)))
for x = 0 to array.size(sr_labels) - 1
    label.delete(array.get(sr_labels, x))
    if array.get(sr_levs, x) and enableSR
        lab_loc = close >= array.get(sr_levs, x) ? label.style_label_up : label.style_label_down
        lab_col = close >= array.get(sr_levs, x) ? colorSup             : colorRes
        array.set(sr_labels, x, label.new(bar_index + label_loc, array.get(sr_levs, x), str.tostring(math.round_to_mintick(array.get(sr_levs, x))), color=lab_col , textcolor=#000000, style=lab_loc))
hlabel := enableSR ? label.new(bar_index + label_loc + math.round(math.sign(label_loc)) * 20, highestph, "High Level : " + str.tostring(highestph), color=hi_col, textcolor=#000000, style=label.style_label_down) : na
llabel := enableSR ? label.new(bar_index + label_loc + math.round(math.sign(label_loc)) * 20, lowestpl , "Low  Level : " + str.tostring(lowestpl) , color=lo_col, textcolor=#000000, style=label.style_label_up  ) : na











//ORDER BLOCK
// box_ob            = input.bool(true, "Toggle Order Block", group="ORDER BLOCK")
// box_hide_gray     = input.bool(true, "Hide gray boxes", group="ORDER BLOCK")
bos_type          = input.string("Close and Open", "MSB trigger", ["High and Low", "Close and Open"], group="ORDER BLOCK")
box_sv            = input.bool(true, "Plot Order Block boxes", group="ORDER BLOCK")
box_test_delay    = input.int(3, "Delay to count test of Order Block box", 1, group="ORDER BLOCK")
box_fill_delay    = input.int(3, "Delay to count fill of Order Block box", 1, group="ORDER BLOCK")
box_test_sv       = input.bool(true, "Dim tested Order Block boxes", group="ORDER BLOCK")
box_stop_sv       = input.bool(true, "Stop plotting filled Order Block boxes", group="ORDER BLOCK")



// Get components

var float[] pvh1_price     = array.new_float(1000, na)
var int[]   pvh1_time      = array.new_int  (1000, na)
var float[] pvl1_price     = array.new_float(1000, na)
var int[]   pvl1_time      = array.new_int  (1000, na)
var float[] pvh2_price     = array.new_float(1000, na)
var int[]   pvh2_time      = array.new_int  (1000, na)
var float[] pvl2_price     = array.new_float(1000, na)
var int[]   pvl2_time      = array.new_int  (1000, na)
var float   htcmrll_price  = na
var int     htcmrll_time   = na
var float   ltcmrhh_price  = na
var int     ltcmrhh_time   = na
var box[]   long_boxes     = array.new_box()
var box[]   short_boxes    = array.new_box()
var float   temp_pv_0      = na
var float   temp_pv_1      = na
var float   temp_pv_2      = na
bool        pvh            = high < high[1] and high[1] > high[6]
bool        pvl            = low  > low [1] and low [1] < low [6]
int         pv1_time       = bar_index[1]
float       pv1_high       = high[1]
float       pv1_low        = low [1]
float       trigger_high   = bos_type == "High and Low" ? high : math.max(open, close)
float       trigger_low    = bos_type == "High and Low" ? low  : math.min(open, close)


// Colors
green    = #00DD00, green50  = color.new(green, 50),  green20  = color.new(green, 80)
red      = #DD0000, red50    = color.new(red, 50),    red20    = color.new(red, 80)
silver   = #B2B5BE, silver50 = color.new(silver, 50), silver20 = color.new(silver, 80)
// Plots


if box_ob and barstate.isconfirmed
    if pvh
        array.pop(pvh1_price)
        array.pop(pvh1_time)
        array.unshift(pvh1_price, pv1_high)
        array.unshift(pvh1_time, pv1_time)
        if array.size(pvh1_price) > 6
            temp_pv_0 := array.get(pvh1_price, 0)
            temp_pv_1 := array.get(pvh1_price, 1)
            temp_pv_2 := array.get(pvh1_price, 6)
            if temp_pv_0 > temp_pv_1
                for i = 0 to array.size(pvl1_time) - 1 by 1
                    temp_ltcmrhh_time = array.get(pvl1_time, i)
                    if temp_ltcmrhh_time < array.get(pvh1_time, 0)
                        ltcmrhh_price := array.get(pvl1_price, i)
                        ltcmrhh_time := temp_ltcmrhh_time
                        break
            if temp_pv_0 < temp_pv_1 and temp_pv_1 > temp_pv_2
                array.pop(pvh2_price)
                array.pop(pvh2_time)
                array.unshift(pvh2_price, temp_pv_1)
                array.unshift(pvh2_time, array.get(pvh1_time, 1))
    if pvl
        array.pop(pvl1_price)
        array.pop(pvl1_time)
        array.unshift(pvl1_price, pv1_low)
        array.unshift(pvl1_time, pv1_time)
        if array.size(pvl1_price) > 6
            temp_pv_0 := array.get(pvl1_price, 0)
            temp_pv_1 := array.get(pvl1_price, 1)
            temp_pv_2 := array.get(pvl1_price, 6)
            if temp_pv_0 < temp_pv_1
                for i = 0 to array.size(pvh1_time) - 1 by 1
                    temp_htcmrll_time = array.get(pvh1_time, i)
                    if temp_htcmrll_time < array.get(pvl1_time, 0)
                        htcmrll_price := array.get(pvh1_price, i)
                        htcmrll_time := temp_htcmrll_time
                        break
            if temp_pv_0 > temp_pv_1 and temp_pv_1 < temp_pv_2
                array.pop(pvl2_price)
                array.pop(pvl2_time)
                array.unshift(pvl2_price, temp_pv_1)
                array.unshift(pvl2_time, array.get(pvl1_time, 1))
    if trigger_high > htcmrll_price
        if box_sv
            loBox = box.new(left=array.get(pvl1_time, 0), top=math.min(high[bar_index - array.get(pvl1_time, 0)], high[bar_index - array.get(pvl1_time, 0) + 1]), right=bar_index, bottom=array.get(pvl1_price, 0), bgcolor=color.rgb(0, 255, 0, 80), border_color=color.rgb(0, 255, 0, 80), extend=extend.right)
            if array.size(long_boxes) >= 25
                box.delete(array.shift(long_boxes))
            array.push(long_boxes, loBox)
        htcmrll_price := na
        htcmrll_price
    if trigger_low < ltcmrhh_price
        if box_sv
            hiBox = box.new(left=array.get(pvh1_time, 0), top=array.get(pvh1_price, 0), right=bar_index, bottom=math.max(low[bar_index - array.get(pvh1_time, 0)], low[bar_index - array.get(pvh1_time, 0) + 1]), bgcolor=color.rgb(255, 0, 0, 80), border_color=color.rgb(255, 0, 0, 80), extend=extend.right)
            if array.size(short_boxes) >= 25
                box.delete(array.shift(short_boxes))
            array.push(short_boxes, hiBox)
        ltcmrhh_price := na
        ltcmrhh_price
    if array.size(short_boxes) > 0
        for i = array.size(short_boxes) - 1 to 0 by 1
            tbox = array.get(short_boxes, i)
            top = box.get_top(tbox)
            bottom = box.get_bottom(tbox)
            if trigger_high > bottom and box.get_left(tbox) + box_test_delay < bar_index and box_test_sv
                if box_hide_gray
                    box.set_bgcolor(tbox, #00000000)
                    box.set_border_color(tbox, #00000000)
                else
                    box.set_bgcolor(tbox, color.rgb(192, 192, 192, 80))
                    box.set_border_color(tbox, color.rgb(192, 192, 192, 80))
            if trigger_high > top and box.get_left(tbox) + box_fill_delay < bar_index
                if box_stop_sv
                    box.set_right(tbox, bar_index)
                    box.set_extend(tbox, extend.none)
                    array.remove(short_boxes, i)
    if array.size(long_boxes) > 0
        for i = array.size(long_boxes) - 1 to 0 by 1
            lbox = array.get(long_boxes, i)
            top = box.get_top(lbox)
            bottom = box.get_bottom(lbox)
            if trigger_low < top and box.get_left(lbox) + box_test_delay < bar_index and box_test_sv
                if box_hide_gray
                    box.set_bgcolor(lbox, #00000000)
                    box.set_border_color(lbox, #00000000)
                else
                    box.set_bgcolor(lbox, color.rgb(192, 192, 192, 80))
                    box.set_border_color(lbox, color.rgb(192, 192, 192, 80))
            if trigger_low < bottom and box.get_left(lbox) + box_fill_delay < bar_index
                if box_stop_sv
                    box.set_right(lbox, bar_index)
                    box.set_extend(lbox, extend.none)
                    array.remove(long_boxes, i)






//////////////////////////////////////////////////////////////////////
//                                                                  //
//                         REVISION HISTORY                         //
//    v 1.0 Initial release                                         //
//    v 1.1 Added interface elements and refactored code            //
//    v. 1.2 Added ability to set EMA length                        //
//                                                                  //
//////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                //
//              This indicator is an English version of the "Mtf Supertrend Table"                //
//                  coded by FxTraderProAsistan. Credit goes to him. I have                   //
//               modified this version for my own needs, in the English language.                 //
//                     Future enhancements will include alerts to changes in                      //
//                           directions on the time frames specified.                             //
//                                                                                                //
////////////////////////////////////////////////////////////////////////////////////////////////////



// Choose trend calculation to use
grp1 = 'Trend Calculation'
// trendCalc       = input.string(defval = "EMA", title = "Trend Mode", options=["Supertrend", "EMA"], group = grp1)

// Statistics Table
// --------
grp2            = 'Trend Table'
// trendTable          = input(true, 'Show Trend Table', group=grp2)

times1          = input.timeframe('1', 'TimeFrame - A', group=grp2, inline = "1")
showtimes1      = input.bool(true,title="Show", group = grp2, inline = "1")
times2          = input.timeframe('5', 'TimeFrame - B', group=grp2, inline = "2")
showtimes2      = input.bool(true,title="Show", group = grp2, inline = "2")
times3          = input.timeframe('15', 'TimeFrame - C', group=grp2, inline = "3")
showtimes3      = input.bool(true,title="Show", group = grp2, inline = "3")
times4          = input.timeframe('30','TimeFrame - D', group=grp2, inline = "4")
showtimes4      = input.bool(true,title="Show", group = grp2, inline = "4")
times5          = input.timeframe('60', 'TimeFrame - E', group=grp2, inline = "5")
showtimes5      = input.bool(true,title="Show", group = grp2, inline = "5")
times6          = input.timeframe('240', 'TimeFrame - F', group=grp2, inline = "6")
showtimes6      = input.bool(true,title="Show", group = grp2, inline = "6")
// showDXY         = input.bool(false, title = 'Show DXY', group = grp2)
 
// Dashboard Settings
grp3 = 'Table Display'
dashColor       = input.color(color.new(#00b2ff,0) , 'Background Color ', group=grp3)
upColor         = input.color(color.green , 'Up Trend Color ', group=grp3)
downColor       = input.color(color.red , 'Down Trend Color ', group=grp3)
TablePos        = input.string('Bottom Right', 'Table Position', ['Top Right', 'Top Center', 'Middle Right', 'Bottom Left',"Bottom Right"], group=grp3)
TablePosTextCol = input.color(color.black, 'Text Color', group=grp3)

TextSize1       = input.string('Small', 'Table Font Size', ['Normal', 'Small', 'Large', 'Huge'], group=grp3)
textSize        = TextSize1=='Huge' ? size.huge : TextSize1=='Normal'? size.small : TextSize1=='Small'? size.tiny : size.normal

tabPos = TablePos == 'Top Right' ? position.top_right : TablePos == 'Bottom Left' ? position.bottom_left : TablePos == 'Middle Right' ? position.middle_right : TablePos == 'Bottom Right' ? position.bottom_right : TablePos == 'Top Center' ? position.top_center : position.bottom_right

var SuperTrendTable  = table.new(tabPos, 50, 50, color.new(color.black,100), color.new(color.black,100), 1, color.new(color.black,1),1)

//------------------------
grp4 = 'SuperTrend Settings'
atrPeriod = input(10, "ATR Length", group = grp4)
factor = input.float(3.0, "Factor", step = 0.01, group = grp4)

grp5 = 'EMA Trend Settings'
fastEMA = input.int(defval = 20, title = 'Fast EMA', minval = 1, maxval = 600, step = 1, group = grp5)
slowEMA = input.int(defval = 50, title = 'Slow EMA', minval = 1, maxval = 600, step = 1, group = grp5)

conditionSuper = 0.0

// Super Trend Calculation
if trendCalc == 'Supertrend'
    [supertrend, direction] = ta.supertrend(factor, atrPeriod)
    conditionSuper := direction < 0 ? 1 : direction > 0 ? -1 : na

// EMA Calculation

is20EMAHigherThan50EMA() =>
    ema20 = ta.ema(close, fastEMA)
    ema50 = ta.ema(close, slowEMA)
    ema20 > ema50 ? -1 : 1

if trendCalc == "EMA"
    emadirection = is20EMAHigherThan50EMA()
    conditionSuper := emadirection < 0 ? 1 : emadirection > 0 ? -1 : na


functionSuper()=>
    conditionSuper
    
functionSuperColor(x) => x==" Up " ? upColor : x== "Down" ? downColor : na

// Function to convert minutes to hours if divisible by 60
minutesToHours(timeframe) =>
    
    // Check if the timeframe is only in minutes
    containsLetters = str.match(timeframe, "[a-zA-Z]")
 
    if na(containsLetters)
        if str.tonumber(timeframe) % 60 == 0
            result = "H" + str.tostring(str.tonumber(timeframe) / 60)
        else
            result = "M" + str.tostring(str.tonumber(timeframe))
    else
        result = containsLetters



fTable(colNumber,times,symbol )=>

    // Depending upon user input, use the appropriate calculation for newSuper (Supertrend)
    newSuper = request.security(symbol, times, functionSuper())
    newSuperDirection = newSuper == 1 ? " Up "   : newSuper == -1 ? "Down"  : na
    superColor=functionSuperColor(newSuperDirection)

    if trendTable
        table.cell(SuperTrendTable, 0, 0, "TimeFrame"    , text_color=TablePosTextCol, text_size=textSize, bgcolor=dashColor)
        table.cell(SuperTrendTable, 0, 1, syminfo.ticker, text_color=TablePosTextCol, text_size=textSize, bgcolor=dashColor)

        tfDes   = times==''? timeframe.period : minutesToHours(times)

        if symbol != "DXY"
            table.cell(SuperTrendTable,colNumber, 0, tfDes  , text_color=TablePosTextCol, text_size=textSize, bgcolor=dashColor)
            table.cell(SuperTrendTable,colNumber, 1, newSuperDirection, text_color=TablePosTextCol, text_size=textSize, bgcolor=superColor, tooltip = str.tostring(symbol))
        if showDXY and symbol == "DXY"
            table.cell(SuperTrendTable, 0, 3, "DXY"    , text_color=TablePosTextCol, text_size=textSize, bgcolor=dashColor)
            table.cell(SuperTrendTable,colNumber, 3, newSuperDirection, text_color=TablePosTextCol, text_size=textSize, bgcolor=superColor, tooltip = str.tostring(symbol))

symbol = syminfo.tickerid 
dxy = syminfo.ticker("TVC:DXY")
if showtimes1
    fTable(1,times1, symbol)
if showtimes2
    fTable(2,times2, symbol)
if showtimes3
    fTable(3,times3, symbol)
if showtimes4
    fTable(4,times4, symbol)
if showtimes5
    fTable(5,times5, symbol)
if showtimes6
    fTable(6,times6, symbol)


// Calculate DXY Special Selection
if showDXY
    if showtimes1
        fTable(1,times1, dxy)
    if showtimes2
        fTable(2,times2, dxy)
    if showtimes3
        fTable(3,times3, dxy)
    if showtimes4
        fTable(4,times4, dxy)
    if showtimes5
        fTable(5,times5, dxy)
    if showtimes6
        fTable(6,times6, dxy)   





// Trendlines

// showTL      = input(true, 'TrendLine', group = 'TrendLines')

//general
f_barssince(_cond, _count) =>
    _barssince = bar_index - ta.valuewhen(_cond, bar_index, _count)
    _barssince

barssince(_cond, _count) => int(math.max(1, nz(f_barssince(_cond, _count))))
f_vw(cond, expr, count) => ta.valuewhen(cond, expr, count)

tostring(x, y)=> x + str.tostring(y)

var int dec = str.length(str.tostring(syminfo.mintick))-2

// Trendlines
gr5         = 'Trendlines'
showPriceTl = false
newestTL    = true
newestBreak = true
// periodlen   = input.string('Adaptive', 'Trendline Term', ['Long Term', 'Short Term','Adaptive'])
period = (periodlen == 'Adaptive' ? 30 : periodlen == 'Long Term' ? 40 : periodlen == 'Short Term' ? 20 : 0)
//period      = input(30, 'Trendline Period')
srcI        = input.string('Wick', 'TrendLine Source', ['Close Body', 'Wick'])
srcL        = srcI=='Wick'? low  : close
srcH        = srcI=='Wick'? high : close
lStyleI     = input.string('Solid', 'TrendLine Style', ['Solid', 'Dashed', 'Dotted'])
y2_mult     = 1
lStyle      = lStyleI=='Solid'? line.style_solid : lStyleI=='Dashed'? line.style_dashed : line.style_dotted
lWidth      = input(1, 'TrendLine Width')
lColor      = color.blue
supTextCol  = color.red
resTextCol  = color.blue

truncate(number) =>
    factor = math.pow(10, dec)
    int(number * factor) / factor

EndTime     = timestamp('19 Jan 2022 00:00 +0000')
inDateRange = time<=EndTime

fVwSeries (x, xVal, xBar)=>
    x0      = truncate(ta.valuewhen(x, xVal, 0))
    x1      = truncate(ta.valuewhen(x, xVal, 1))
    x2      = truncate(ta.valuewhen(x, xVal, 2))
    x0Bar   = ta.valuewhen(x, xBar, 0) - f_barssince(x, 0)
    x1Bar   = ta.valuewhen(x, xBar, 1) - f_barssince(x, 1)
    x2Bar   = ta.valuewhen(x, xBar, 2) - f_barssince(x, 2)
    
    [x0, x1, x2, x0Bar, x1Bar, x2Bar]


fTst(x, y)=> x + str.tostring(y)

phFound     = ta.pivothigh(srcH, period, period)
plFound     = ta.pivotlow (srcL, period, period)
phVal       = ta.valuewhen(phFound, srcH[period], 0)
plVal       = ta.valuewhen(plFound, srcL[period], 0)
phVal1      = ta.valuewhen(phFound, srcH[period], 1)
plVal1      = ta.valuewhen(plFound, srcL[period], 1)

a_bar_time  = time - time[1]
noneCol     = color.new(color.red, 100)

fGetPriceTl(slope_, x2_, y2_) =>
    current_price  = y2_ + (slope_/(x2_ - time))
    current_price

f_trendline(cond_, y1Val_, x1Bar_, y2Val_, x2Bar_, color_, tlPriceText, textCol) =>
    
    x1      = ta.valuewhen(cond_, time[x1Bar_], 0)
    x2      = ta.valuewhen(cond_, time[x2Bar_], 0)
    y1      = ta.valuewhen(cond_, y1Val_, 0)
    y2      = ta.valuewhen(cond_, y2Val_, 0)
    slope_  = ta.valuewhen(cond_, (y2-y1)/(x2-x1), 0)

    currentPrice    = truncate(y2 + (time-x2)*slope_) 
    var label tlPrice     = na
    
    if close and newestTL
        a_trendline = line.new (x1, y1, time,  currentPrice, xloc.bar_time, color=lColor, style=lStyle, width=lWidth)
        line.delete (a_trendline[1])
        
        a_trendline
    
    newY2   = x2 + (y2_mult * a_bar_time * 25)
    
    if cond_ and not newestTL
        a_trendline = line.new(x1, y1, newY2,  currentPrice, xloc.bar_time, color=lColor, style=lStyle, width=lWidth)
        a_trendline
    if showPriceTl
        tlPrice     := label.new(bar_index+10, currentPrice, fTst(tlPriceText, currentPrice), color=noneCol, style=label.style_label_left, textcolor=textCol)
        label.delete(tlPrice[1])

    currentPrice

newUp   = phFound and phVal<phVal1 and showTL
newLo   = plFound and plVal>plVal1 and showTL
upperTl = f_trendline(newUp, phVal1, f_barssince(phFound,1)+period, phVal, f_barssince(phFound,0)+period,color.black, 'Upper = ', resTextCol)
lowerTl = f_trendline(newLo, plVal1, f_barssince(plFound,1)+period, plVal, f_barssince(plFound,0)+period,color.black, 'Lower = ', supTextCol)

highestSince    = ta.highest(srcH, barssince(phFound and phVal<phVal1 and showTL,0))
lowestSince     = ta.lowest (srcL, barssince(plFound and plVal>plVal1 and showTL,0))
breakUpper      = srcH[1]<upperTl[1] and srcH>upperTl
breakLower      = srcL[1]>lowerTl[1] and srcL<lowerTl






// MTF S/R //
group               = "MULTI-TIMEFRAME S/R AREA (Beta Feature)"
// showSR              = input.bool(true, title = "", inline = "01", group=group)
// timef               = input.timeframe("", "", inline = "01", group=group)
levels              = input.int(7 , "Levels", inline = "01", group = group)
linewidth           = input.int(1, "Width", inline = "02", group = group) * 20
supportcolor        = #0089774b
resistancecolor     = #b228344b
labelon             = input.string("On", "Label", ["On", "Off"], inline = "03", group = group)
labelsize           = input.string("Default", "Size", ["Small", "Default", "Large"], inline = "03", group = group)
labelcol            = input.color(#787b86, "", inline = "03", group = group)
labelloc            = input.int(10, "Offset", inline = "04", group = group) + 30
showtimef           = input.bool(true, "Show Timeframe", inline = "04", group = group)
showtprice          = input.bool(false, "Show Price", inline = "04", group = group)


// get data on ticker based on chosen timeframe
src_c = request.security(syminfo.tickerid,timef,close, gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off)
src_o = request.security(syminfo.tickerid,timef,open, gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off)
f_resInMinutes() =>
    _resInMinutes = timeframe.multiplier * (timeframe.isseconds ? 1. / 60 : timeframe.isminutes ? 1. : timeframe.isdaily ? 60. * 24 : timeframe.isweekly ? 60. * 24 * 7 : timeframe.ismonthly ? 60. * 24 * 30.4375 : na)
    _resInMinutes
f_timefResInMinutes(_res) =>
    request.security(syminfo.tickerid, _res, f_resInMinutes())
f_timefIsIntraday(_res) =>
    [intraday, daily, weekly, monthly] = request.security(syminfo.tickerid, _res, [timeframe.isintraday, timeframe.isdaily, timeframe.isweekly, timeframe.ismonthly])
    check = intraday ? "Intraday" : daily ? "Daily" : weekly ? "Weekly" : monthly ? "Monthly" : "Error" 
    check
mtimef_multiplier = int (f_timefResInMinutes(timef) / f_resInMinutes())
prd_ = 10
maxnumpp = 284
ChannelW_ = 10
min_strength = 2
prd_ := prd_ * mtimef_multiplier
float src1 = math.max(src_c, src_o) 
float src2 = math.min(src_c, src_o)
float src3 = math.max(close, open)  
float src4 = math.min(close, open)   
float phsa = ta.pivothigh(src1, prd_, prd_)
float plsa = ta.pivotlow(src2, prd_, prd_)
Lstyle = line.style_solid
timef_res = f_timefIsIntraday(timef)
timef_text = str.tostring(timef)
if str.tostring(timef) == ""
    timef_text := na(timeframe.multiplier / 60) ? timeframe.period : timeframe.multiplier < 60 ?  timeframe.period + " M |" : str.tostring(timeframe.multiplier / 60) + " H |"
else if timef_res == "Intraday"
    timef_text := na(str.tonumber(timef) / 60) ? str.tostring(timef) : str.tonumber(timef) < 60 ?  str.tostring(timef) + " M |" : str.tostring(str.tonumber(timef) / 60) + " H |"
else
    timef_text := str.tostring(timef)
//calculate maximum S/R channel zone width
prdhighest_ = request.security(syminfo.tickerid, timef, ta.highest(300))
prdlowest_ = request.security(syminfo.tickerid, timef, ta.lowest(300))
cwidth_ = (prdhighest_ - prdlowest_) * ChannelW_ / 100
var pivotvals = array.new_float(0)
if phsa or plsa
    array.unshift(pivotvals, phsa ? phsa : plsa)
    if array.size(pivotvals) > maxnumpp  // limit the array size
        array.pop(pivotvals)
get_sr_vals(ind) =>
    float lo = array.get(pivotvals, ind)
    float hi = lo
    int numpp = 0
    for y = 0 to array.size(pivotvals) - 1 by 1
        float cpp = array.get(pivotvals, y)
        float wdth = cpp <= lo ? hi - cpp : cpp - lo
        if wdth <= cwidth_  // fits the max channel width?
            lo := cpp <= lo ? cpp : lo
            hi := cpp > lo ? cpp : hi
            numpp += 1
            numpp
    [hi, lo, numpp]
var sr_up_level = array.new_float(0)
var sr_dn_level = array.new_float(0)
sr_strength = array.new_float(0)

find_loc(strength) =>
    ret = array.size(sr_strength)
    for i = ret > 0 ? array.size(sr_strength) - 1 : na to 0 by 1
        if strength <= array.get(sr_strength, i)
            break
        ret := i
        ret
    ret

check_sr(hi, lo, strength) =>
    ret = true
    for i = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
        //included?
        if array.get(sr_up_level, i) >= lo and array.get(sr_up_level, i) <= hi or array.get(sr_dn_level, i) >= lo and array.get(sr_dn_level, i) <= hi
            if strength >= array.get(sr_strength, i)
                array.remove(sr_strength, i)
                array.remove(sr_up_level, i)
                array.remove(sr_dn_level, i)
                ret
            else
                ret := false
                ret
            break
    ret

var sr_lines_ = array.new_line(11, na)
var sr_labels_ = array.new_label(11, na)
var timef_labels = array.new_label(11, na)

if phsa or plsa
    //because of new calculation, remove old S/R levels
    array.clear(sr_up_level)
    array.clear(sr_dn_level)
    array.clear(sr_strength)
    //find S/R zones
    for x = 0 to array.size(pivotvals) - 1 by 1
        [hi, lo, strength] = get_sr_vals(x)
        if check_sr(hi, lo, strength)
            loc = find_loc(strength)
            // if strength is in first levels sr then insert it to the arrays 
            if loc < levels and strength >= min_strength
                array.insert(sr_strength, loc, strength)
                array.insert(sr_up_level, loc, hi)
                array.insert(sr_dn_level, loc, lo)
                // keep size of the arrays = 5
                if array.size(sr_strength) > levels
                    array.pop(sr_strength)
                    array.pop(sr_up_level)
                    array.pop(sr_dn_level)

    for x = 1 to 10 by 1
        line.delete(array.get(sr_lines_, x))
        label.delete(array.get(sr_labels_, x))
        label.delete(array.get(timef_labels, x))

    for x = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
        float mid = math.round_to_mintick((array.get(sr_up_level, x) + array.get(sr_dn_level, x)) / 2)
        if showSR
            array.set(sr_lines_, x + 1, line.new(x1=bar_index, y1=mid, x2=bar_index - 1, y2=mid, extend=extend.both, color=mid >= close ? resistancecolor : supportcolor, style=Lstyle, width=linewidth))
            if labelon == "On" 
                size = labelsize == "Small" ? size.small : labelsize == "Default" ? size.normal : size.large
                array.set(sr_labels_, x + 1, label.new(x=bar_index + labelloc, y=mid, text=(showtimef ? timef_text : na) + (showtprice ? (" " + str.tostring(mid)) : na), color=mid >= close ? #ff525200 : #00e67700, textcolor=labelcol,
                 size = size, style=label.style_label_left))

f_crossed_over() =>
    ret = false
    for x = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
        float mid = math.round_to_mintick((array.get(sr_up_level, x) + array.get(sr_dn_level, x)) / 2)
        if close[1] <= mid and close > mid
            ret := true
            ret
    ret

f_crossed_under() =>
    ret = false
    for x = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
        float mid = math.round_to_mintick((array.get(sr_up_level, x) + array.get(sr_dn_level, x)) / 2)
        if close[1] >= mid and close < mid
            ret := true
            ret
    ret

alertcondition(f_crossed_over(), title= "Price Breaks Resistance", message = "Price Breaks Resistance, TimeFrame={{interval}}")
alertcondition(f_crossed_under(), title="Price Loses Support", message="Price Loses Support, TimeFrame={{interval}}")




//RSI
// rsicol = input.bool(false, title='Show RSI colors?', group='Settings', tooltip='Show RSI Levels On Bars')
srcRSI = close
lenRSI = input.int(14, minval=1, title='RSI Length', group='RSI Settings')
up = ta.rma(math.max(ta.change(srcRSI), 0), lenRSI)
down = ta.rma(-math.min(ta.change(srcRSI), 0), lenRSI)
rsi = down == 0 ? 100 : up == 0 ? 0 : 100 - 100 / (1 + up / down)

//coloring method below
srcRSI1 = close
lenRSI1 = input.int(60, minval=1, title='Over Bought', group='RSI Settings')
srcRSI2 = close
lenRSI2 = input.int(40, minval=1, title='Over Sold', group='RSI Settings')
isup() =>
    rsi > lenRSI1
isdown() =>
    rsi < lenRSI2
barcolor(rsicol and isup() ? color.yellow : rsicol and isdown() ? color.orange : na)